// processor definitions
#include "inc/lm4f120h5qr.h"


#include "inc/hw_types.h"
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "driverlib/interrupt.h"
#include "driverlib/gpio.h"
#include "driverlib/rom.h"
#include "driverlib/rom_map.h"
#include "driverlib/sysctl.h"

/*#include "inc/hw_ints.h"*/
/*#include "inc/hw_memmap.h"*/
/*#include "inc/hw_types.h"*/
/*#include "driverlib/sysctl.h"*/
/*#include "driverlib/interrupt.h"*/
#include "driverlib/timer.h"
/*#include "driverlib/gpio.h"*/
/*#include "inc/hw_gpio.h"*/
/*#include "inc/hw_sysctl.h"*/
/*#include "driverlib/rom.h"*/

/*#include "driverlib/debug.h"*/
/*#include "driverlib/fpu.h"*/
/*#include "utils/uartstdio.h"*/


#define PA_0 GPIO_PIN_0	//0x00000001
#define PA_1 GPIO_PIN_1	//0x00000002
#define PA_2 GPIO_PIN_2	//0x00000004
#define PA_3 GPIO_PIN_3	//0x00000008
#define PA_4 GPIO_PIN_4	//0x00000010
#define PA_5 GPIO_PIN_5	//0x00000020
#define PA_6 GPIO_PIN_6	//0x00000040
#define PA_7 GPIO_PIN_7	//0x00000080

#define PB_0 GPIO_PIN_0	//0x00000001
#define PB_1 GPIO_PIN_1	//0x00000002
#define PB_2 GPIO_PIN_2	//0x00000004
#define PB_3 GPIO_PIN_3	//0x00000008
#define PB_4 GPIO_PIN_4	//0x00000010
#define PB_5 GPIO_PIN_5	//0x00000020
#define PB_6 GPIO_PIN_6	//0x00000040
#define PB_7 GPIO_PIN_7	//0x00000080

#define PC_0 GPIO_PIN_0	//0x00000001
#define PC_1 GPIO_PIN_1	//0x00000002
#define PC_2 GPIO_PIN_2	//0x00000004
#define PC_3 GPIO_PIN_3	//0x00000008
#define PC_4 GPIO_PIN_4	//0x00000010
#define PC_5 GPIO_PIN_5	//0x00000020
#define PC_6 GPIO_PIN_6	//0x00000040
#define PC_7 GPIO_PIN_7	//0x00000080

#define PD_0 GPIO_PIN_0	//0x00000001
#define PD_1 GPIO_PIN_1	//0x00000002
#define PD_2 GPIO_PIN_2	//0x00000004
#define PD_3 GPIO_PIN_3	//0x00000008
#define PD_4 GPIO_PIN_4	//0x00000010
#define PD_5 GPIO_PIN_5	//0x00000020
#define PD_6 GPIO_PIN_6	//0x00000040
#define PD_7 GPIO_PIN_7	//0x00000080

#define PE_0 GPIO_PIN_0	//0x00000001
#define PE_1 GPIO_PIN_1	//0x00000002
#define PE_2 GPIO_PIN_2	//0x00000004
#define PE_3 GPIO_PIN_3	//0x00000008
#define PE_4 GPIO_PIN_4	//0x00000010
#define PE_5 GPIO_PIN_5	//0x00000020
#define PE_6 GPIO_PIN_6	//0x00000040
#define PE_7 GPIO_PIN_7	//0x00000080

#define PF_0 GPIO_PIN_0	//0x00000001
#define PF_1 GPIO_PIN_1	//0x00000002
#define PF_2 GPIO_PIN_2	//0x00000004
#define PF_3 GPIO_PIN_3	//0x00000008
#define PF_4 GPIO_PIN_4	//0x00000010
#define PF_5 GPIO_PIN_5	//0x00000020
#define PF_6 GPIO_PIN_6	//0x00000040
#define PF_7 GPIO_PIN_7	//0x00000080

#define redled GPIO_PIN_1
#define bluled GPIO_PIN_2
#define grnled GPIO_PIN_3

#define btn1 PF_0
#define btn2 PF_4


int delay(int time);
unsigned long ulPeriod;
int count = 0;
int flip = 0;
int readValue = 0;

extern void Timer0IntHandler(void);
extern void PortAIntHandler(void);
extern void PortFIntHandler(void);

int main(void) {

	//enable clock, 200MHz/5 = 40MHz
	ROM_SysCtlClockSet(SYSCTL_SYSDIV_5 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ | SYSCTL_OSC_MAIN);
	
	//enable clock, use crystal at 1MHz
	//ROM_SysCtlClockSet(SYSCTL_RCC_XTAL_1MHZ | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ | SYSCTL_OSC_MAIN);

	// enable PORT A,B,D,E,F GPIO and Timer0 peripheral
	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA|SYSCTL_PERIPH_GPIOB|SYSCTL_PERIPH_GPIOD|SYSCTL_PERIPH_GPIOE|SYSCTL_PERIPH_GPIOF);
	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
	ROM_SysCtlDelay(200000);

	// set LED PORT D pins as outputs
	ROM_GPIOPinTypeGPIOOutput(GPIO_PORTD_BASE, (PD_0 | PD_1 | PD_2 | PD_3 | PD_4 | PD_5));
	ROM_GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, (PA_5 | PA_6 | PA_7));
	ROM_GPIOPinTypeGPIOOutput(GPIO_PORTB_BASE, (PB_4));
	ROM_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, redled|bluled|grnled);
	
	// set Port A 2,3,4 and Port B 6,7 as inputs
	ROM_GPIOPinTypeGPIOInput(GPIO_PORTA_BASE, (PA_2 | PA_3 | PA_4));
	ROM_GPIOPinTypeGPIOInput(GPIO_PORTD_BASE, (PD_6 | PD_7));
	ROM_GPIOPinTypeGPIOInput(GPIO_PORTF_BASE, (btn1 | btn2));

	//set timer period: 40MHz/10/2 = 2MHz = 0.5us
	//for 1000us = 1ms use Div by 0.1 and then 4, 40MHz / 0.1 / 4 = 1ms
	ROM_TimerConfigure(TIMER0_BASE, TIMER_CFG_PERIODIC);
	ulPeriod = (ROM_SysCtlClockGet() / 10 / 1);		//for 1ms
	ROM_TimerLoadSet(TIMER0_BASE, TIMER_A, ulPeriod - 1);

	//unlock gpiof
	

	
	//GPIO interrupt setup
	ROM_IntEnable(INT_GPIOA|INT_GPIOF);			//added
	ROM_GPIOPinIntEnable(GPIO_PORTA_BASE, PA_2);		//added
	ROM_GPIOPinIntEnable(GPIO_PORTF_BASE, (btn1|btn2));

	ROM_GPIOIntTypeSet(GPIO_PORTA_BASE, PA_2, GPIO_FALLING_EDGE);
	ROM_GPIOPadConfigSet(GPIO_PORTA_BASE, PA_2, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU);

	ROM_GPIOIntTypeSet(GPIO_PORTF_BASE, (btn1|btn2), GPIO_FALLING_EDGE);
	ROM_GPIOPadConfigSet(GPIO_PORTF_BASE, (btn1|btn2), GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU);
	
	//initial interrupt clear
	ROM_GPIOPinIntClear(GPIO_PORTA_BASE, PA_2);
	//ROM_GPIOPinIntClear(GPIO_PORTF_BASE, (btn1|btn2));

	ROM_IntEnable(INT_GPIOA);					//might use this instead
	ROM_IntEnable(INT_GPIOF);

	//Timer interrupt setup
	ROM_TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
	ROM_IntEnable(INT_TIMER0A);
	ROM_TimerEnable(TIMER0_BASE, TIMER_A);
	
	//enable all interrupts
	ROM_IntMasterEnable();
	

	//init pins
	ROM_GPIOPinWrite(GPIO_PORTD_BASE, 0xff, 0);
	//ROM_GPIOPinWrite(GPIO_PORTF_BASE, redled, 0);

	// loop forever
	while(1)
	{
		//ROM_GPIOPinWrite(GPIO_PORTF_BASE, bluled, bluled);
		ROM_SysCtlDelay(200000);
		//ROM_GPIOPinWrite(GPIO_PORTF_BASE, bluled, ~bluled);
		ROM_SysCtlDelay(200000);
	}
}

void Timer0IntHandler(void)
{
	//clear interrupt
	ROM_TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT);

	if(!flip) count++;
	else count--;

	count = count%10;	

	if(count == 0) {
		flip = flip ^ 0xff;
		count = 10;
	}

	//do led shifting here
	ROM_GPIOPinWrite(GPIO_PORTD_BASE, 0xff, (1<<(count-1))|(1<<(count-2)));
	ROM_GPIOPinWrite(GPIO_PORTB_BASE, 0xff, (1<<(count-1))|(1<<(count-2)));
	ROM_GPIOPinWrite(GPIO_PORTA_BASE, 0xff, (1<<(count-1))|(1<<(count-2)));


	//reset counter value back to ulPeriod
	ROM_TimerLoadSet(TIMER0_BASE, TIMER_A, ulPeriod-1);


	//test
	//ROM_GPIOPinWrite(GPIO_PORTF_BASE, bluled, flip);
}

void PortAIntHandler(void)
{
	ROM_GPIOPinIntClear(GPIO_PORTA_BASE, PA_2);
	//ROM_GPIOPinWrite(GPIO_PORTF_BASE, bluled, bluled);
	ROM_GPIOPinWrite(GPIO_PORTF_BASE, redled, flip);
	
	//read from pins
	readValue = ROM_GPIOPinRead(GPIO_PORTA_BASE, (PA_2 | PA_3 | PA_4));
}

void PortFIntHandler(void)
{
	ROM_GPIOPinIntClear(GPIO_PORTF_BASE, (btn1|btn2));
	//ROM_GPIOPinWrite(GPIO_PORTF_BASE, bluled, bluled);
	ROM_GPIOPinWrite(GPIO_PORTF_BASE, grnled, flip);
	
	//read from pins
	readValue = ROM_GPIOPinRead(GPIO_PORTA_BASE, (PA_2 | PA_3 | PA_4));
}

